<?php

namespace App\Http\Controllers\Admin\Finance\Receivable;

use App\Http\Controllers\Admin\Base\ExchangeRate;
use App\Http\Controllers\Admin\Examine\Record;
use App\Http\Controllers\Controller;
use App\Imports\GenericImport;
use App\Models\airline\base\FlightModel;
use App\Models\base\CurrencyModel;
use App\Models\finance\PayableTakeOrderDetailModel;
use App\Models\finance\PayableTakeOrderModel;
use App\Models\finance\PayableTmpModel;
use App\Models\finance\ReceivableGenericDetailModel;
use App\Models\finance\ReceivableGenericModel;
use App\Models\finance\ReceivableTmpModel;
use App\Models\OrderModel;
use App\Models\RecBillModel;
use App\Models\TakeOrderModel;
use App\Exports\ReceivableGenericExport;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;

class Generic extends Controller
{
    /**
     * 应收账款列表
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function list(Request $request): JsonResponse
    {
        $take_order_sn = $request->input('take_order_sn', '');
        $start_date = $request->input('flight_time_start', '');
        $end_date = $request->input('flight_time_end', '');
        $check_type = $request->input('check_type', '');
        $operator = $request->input('operator', '');
        $servicer = $request->input('servicer', '');
        $customer_id = $request->input('customer_id', '');
        $start_port_code = $request->input('origin', '');
        $arrive_port_code = $request->input('destination', '');
        $master = $request->input('master', '');
        $airline_flight_id = $request->input('airline_flight_id', '');
        $route_id = $request->input('route_id', '');
        $air_company_id = $request->input('air_company_id', '');

        $query = ReceivableGenericModel::with(['take_order', 'flight', 'customer', 'create_admin', 'detail'])->whereHas('customer', function($query) {
            $query->where('is_big', 0);
        });

        if($take_order_sn){
//            $find = TakeOrderModel::query()->where('sn', $take_order_sn)->first();
//            $take_order_id = $find->id ?? 0;
//            $query->where('take_order_id', $take_order_id);

            $query->whereHas('take_order', function($query) use ($take_order_sn) {
                $query->where('sn', 'like', '%' . $take_order_sn . '%');
            });
        }

        if($check_type && $start_date && $end_date){
            if($check_type == 1){
                $query->whereBetween('flight_date', [$start_date, $end_date]);
            }
            if($check_type == 2){
                $query->whereBetween('created_at', [$start_date . ' 00:00:00', $end_date . ' 23:59:59']);
            }
        }

        if($operator){
            $query->where('operator', $operator);
        }

        if($servicer){
            $query->where('servicer', $servicer);
        }

        if($customer_id){
            $query->where('customer_id', $customer_id);
        }

        if($start_port_code || $arrive_port_code || $route_id || $airline_flight_id || $air_company_id){
            $query->whereHas('flight', function($query) use ($start_port_code, $arrive_port_code, $route_id, $airline_flight_id, $air_company_id) {
                if($start_port_code){
                    $query->where('start_port_code', $start_port_code);
                }
                if($arrive_port_code){
                    $query->where('arrive_port_code', $arrive_port_code);
                }
                $query->whereHas('items', function($query) use ($route_id, $airline_flight_id, $air_company_id) {
                    if($route_id){
                        $query->where('route_id', $route_id);
                    }
                    if($airline_flight_id){
                        $query->where('airline_flight_id', $airline_flight_id);
                    }
                    if($air_company_id){
                        $query->where('airline_company_id', $air_company_id);
                    }
                });
            });
        }

        if($master){
            $query->where('master', $master);
        }

        $total = $query->count();

        $total_gross_weight = $query->sum('gross_weight') ?? 0;
        $total_volume_weight = $query->sum('volume_weight') ?? 0;
        $total_charging_weight = $query->sum('charging_weight') ?? 0;
        $total_amount = $query->sum('total_amount') ?? 0;

        $page = $request->input('page', 1);
        $limit = $request->input('limit', 15);

        // 分页
        $list = $query->orderBy('id', 'desc')->forPage($page, $limit)->get()
            ->map(function($item) {
                $origin = $item->flight?->start_port_code;
                $destination = $item->flight?->arrive_port_code;

//                $flight_number_id = $item->flight?->items?->first()->airline_flight_id ?? '';
//                if(!$flight_number_id){
//                    $flight_number = '';
//                }else{
//                    $flight_number = FlightModel::where('id', $flight_number_id)->value('flight_number') ?? '';
//                }

                $flight_number = $item->flight->flight_number ?? '';


                $item->take_order_sn = $item->take_order?->sn ?? '';
                $item->goods_attr = OrderModel::GOODS_ATTR_MAPS[$item->take_order?->goods_attr ??  1] ?? '';
                $item->flight_sn = $item->flight?->sn ?? '';
                $item->customer_name = $item->customer?->name ?? '';
                $item->create_admin_name = $item->create_admin?->name ?? '';
                $item->origin = $origin;
                $item->destination = $destination;
                $item->flight_number = $flight_number;
                $item->take_off_time = $item->flight_date ?? '';
                $item->shipment_date = $item->take_order?->shipment_date ?? '';
                $item->total_amount = $item->detail?->sum('amount') ?? 0;
                return $item;
            });
        
        return $this->success([
            'list' => $list,
            'total' => $total,
            'statistics' => [
                'total_gross_weight' => $total_gross_weight,
                'total_volume_weight' => $total_volume_weight,
                'total_charging_weight' => $total_charging_weight,
                'total_amount' => $total_amount
            ]
        ]);
    }



    public function update(Request $request, int $id)
    {
        $receivable = ReceivableGenericModel::find($id);
        $price = $request->input('air_freight_unit_price', 0);
        $weight = $request->input('charging_weight', 0);

        if (!$receivable) {
            return $this->error('记录不存在');
        }

        DB::beginTransaction();
        try {
            $receivable->air_freight_unit_price = $price;
            $receivable->charging_weight = $weight;
            $receivable->save();

            $detail = ReceivableGenericDetailModel::where('generic_id', $id)->where('name', '空运费')->first();
            if ($detail) {
                $detail->price = $price;
                $detail->number = $weight;
                $detail->amount = round($price * $weight, 2);
                $detail->save();
            }

            DB::commit();

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error('更新失败：' . $e->getMessage());
        }

       return $this->success('更新成功');
    }
    

    
    /**
     * 删除应收账款
     *
     * @param int $id
     * @return JsonResponse
     */
    public function delete(int $id): JsonResponse
    {
        $receivable = ReceivableGenericModel::find($id);
        
        if (!$receivable) {
            return $this->error('记录不存在');
        }
        
        try {
            $receivable->delete();
            return $this->success([], '删除成功');
        } catch (\Exception $e) {
            return $this->error('删除失败：' . $e->getMessage());
        }
    }
    
    /**
     * 导出应收账款
     *
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function export(Request $request)
    {
        return Excel::download(new ReceivableGenericExport($request), '应收账款通用模板_' . date('Y-m-d_H-i-s') . '.xlsx');
    }


    public function import(Request $request)
    {
        $file = $request->file('file');
        if (!$file) {
            return $this->error('请选择文件');
        }

        $import = new GenericImport();
        Excel::import($import, $file);


        $res = $import->get_result();

        if(isset($res->error) && $res->error){
            return $this->error(implode(',', $res->error));
        }

        $lines = $res->lines;

        DB::beginTransaction();
        try {

            $bill = new RecBillModel();
            $bill->sn = getCode('rec_bill', 'ZD', 5);
            $bill->take_order_count = count($lines);
            $bill->save();

            $customer_id = 0; $bill_amount = 0; $flight_date = [];
            foreach ($lines as $line){
                $find = ReceivableGenericModel::where('take_order_id', $line['take_order_id'])->first();

                $flight_date[] = $find->flight_date;

                if(!$find){
                    return $this->error('提单不存在');
                }
                $customer_id = $find->customer_id;

                $detail_arr = [];
                foreach ($line['details'] as $detail){
                    $detail_arr[] = [
                        'take_order_id' => $find->id,
                        'flight_id' => $find->flight_id,
                        'customer_id' => $find->customer_id,
                        'generic_id' => $find->id,
                        'name' => $detail['name'],
                        'amount' => $detail['amount'],
                    ];
                }
                ReceivableGenericDetailModel::where('generic_id', $find->id)->delete();

                ReceivableGenericDetailModel::insert($detail_arr);

                $find->bill_id = $bill->id;
                $find->total_amount = $line['total_amount'];
                $find->air_freight_unit_price = $line['price'];
                $find->status = 1;
                $find->save();

                $bill_amount += $line['total_amount'];
            }

            $bill->customer_id = $customer_id;
            $bill->amount = $bill_amount;
            $bill->start = min($flight_date);
            $bill->end = max($flight_date);
            $bill->examine_record_id = (new Record())->add(4);
            $bill->status = 1;
            $bill->save();

            DB::commit();
        }catch (\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }

        return  $this->success();

    }


    public function create_bill(Request $request)
    {
        $ids = $request->input('ids', []);
        if (!$ids) {
            return $this->error('请选择数据');
        }

        $take_orders = ReceivableGenericModel::whereIn('id', $ids)->whereNull('bill_id')->get();
        if(count($take_orders) != count($ids)){
            return $this->error('请选择未生成账单的订单');
        }

        $customer_ids = $take_orders->pluck('customer_id')->unique()->toArray();
        if (count($customer_ids) > 1) {
            return $this->error('请选择同一客户');
        }
        $customer_id = $customer_ids[0];

        $flight_date = $take_orders->pluck('flight_date')->unique()->toArray();

        $bill_amount = ReceivableGenericDetailModel::whereIn('generic_id', $ids)->sum('amount');


        DB::beginTransaction();
        try {
            $bill = new RecBillModel();
            $bill->sn = getCode('rec_bill', 'ZD', 5);
            $bill->take_order_count = count($take_orders);
            $bill->amount = $bill_amount;
            $bill->customer_id = $customer_id;
            $bill->start = min($flight_date);
            $bill->end = max($flight_date);
            $bill->examine_record_id = (new Record())->add(4);
            $bill->status = 1;
            $bill->save();


            ReceivableGenericModel::whereIn('id', $ids)->update([
                'bill_id' => $bill->id,
                'status' => 1
            ]);
            DB::commit();

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success('操作成功');
    }


    public function detail(Request $request)
    {
        $id = $request->input('id', 0);
        $receivable = ReceivableGenericModel::find($id);
        if (!$receivable) {
            return $this->error('记录不存在');
        }

        $detail = ReceivableGenericDetailModel::with('currency')->where('generic_id', $id)->get();

        $list = $detail->map(function ($item) {
            return [
                'id' => $item->id,
                'name' => $item->name,
                'amount' => $item->amount,
                'price' => $item->price,
                'number' => $item->number,
                'rate' => $item->rate,
                'amount_cny' => $item->amount_cny,
                'currency_id' => $item->currency_id,
                'currency_code' => $item->currency->short_code ?? '',

            ];
        });

        return $this->success(['list' => $list]);
    }


    public function update_detail(Request $request)
    {
        $id = $request->input('id', 0);
        $data = $request->input('detail', []);

        if(!$data){
            return $this->error('明细不能为空');
        }

        $receivable = ReceivableGenericModel::find($id);
        if (!$receivable) {
            return $this->error('记录不存在');
        }

        DB::beginTransaction();
        try {
            foreach ($data as $item){
                if(isset($item['id'])){
                    $detail = ReceivableGenericDetailModel::find($item['id']);
                    $detail->name = $item['name'];
                    $detail->amount = $item['amount'];
                    $detail->save();
                }else{
                    ReceivableGenericDetailModel::insert([
                        'take_order_id' => $id,
                        'flight_id' => $receivable->flight_id,
                        'customer_id' => $receivable->customer_id,
                        'generic_id' => $id,
                        'name' => $item['name'],
                        'amount' => $item['amount'],
                    ]);

                    if($item['name'] == '空运单价'){
                        $receivable->air_freight_unit_price = $item['amount'];
                        $receivable->save();
                    }
                    if($item['name'] == '总金额'){
                        $receivable->total_amount = $item['amount'];
                        $receivable->save();
                    }
                }
            }

            DB::commit();

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error('更新失败：' . $e->getMessage());
        }
        return $this->success();
    }

    public function detail2(Request $request) {
        $take_order_id = $request->input('take_order_id');
        $take_order = TakeOrderModel::with(['customer', 'flight'])->find($take_order_id);
        if(!$take_order) {
            return $this->error('提单不存在');
        }


        $master = $take_order->master;
        if(empty($master)) {
            $master = $take_order->flight->carrier;
        }

        //完善资料
        $perfect = [
            'customer_name' => $take_order->customer->name ?? '',
            'sn' => $take_order->sn,
            'goods_attr' => OrderModel::GOODS_ATTR_MAPS[$take_order->goods_attr] ?? '',
            'flight_date' => $take_order->flight->flight_date ?? '',
            'start_port_code' => $take_order->flight->start_port_code ?? '',
            'arrive_port_code' => $take_order->flight->arrive_port_code ?? '',
            'big_pkgs' => $take_order->orders->sum('big_pkgs') ?? 0,
            'reality_weight' => $take_order->reality_weight ?? 0,
            'operator' => $take_order->operator,
            'servicer' => $take_order->servicer,
            'shipment_date' => $take_order->shipment_date,
            'cca' => $take_order->cca,
            'take_warehouse' => $take_order->take_warehouse,
            'master' => $master,
            'slipt_order_count' => $take_order->slipt_order_count,
            'clr_agent_id' => $take_order->clr_agent_id,
            'clr_agent_name' => $take_order->clr_agent->name ?? '',
            'dec_type' => $take_order->dec_type,
            'dec_type_name' => TakeOrderModel::DEC_TYPE_MAPS[$take_order->dec_type] ?? '',
            'dec_method' => $take_order->dec_method,
            'dec_method_name' => TakeOrderModel::DEC_METHOD_MAPS[$take_order->dec_method] ?? '',
            'dec_agent_id' => $take_order->dec_agent_id,
            'dec_agent_name' => $take_order->dec_agent->name ?? '',
            'fake_brand' => $take_order->fake_brand,
            'origin_ledger' => $take_order->origin_ledger,
            'mix_tick' => $take_order->mix_tick,
            'dec_incidentals' => $take_order->dec_incidentals,
            'dec_incidentals_remark' => $take_order->dec_incidentals_remark,
            'separate_dec_weight' => $take_order->separate_dec_weight,
            'separate_dec_volume' => $take_order->separate_dec_volume,
            'separate_dec_page_fee' => $take_order->separate_dec_page_fee,
            'hk_land' => $take_order->hk_land,
            'hk_land_remark' => $take_order->hk_land_remark,
            'hk_provide' => $take_order->hk_provide,
            'hk_provide_remark' => $take_order->hk_provide_remark,
            'bj_3' => $take_order->bj_3,
            'bj_3_remark' => $take_order->bj_3_remark,
            'bj_8' => $take_order->bj_8,
            'bj_8_remark' => $take_order->bj_8_remark,
            'remark' => $take_order->remark,
            'separate_dec' => $take_order->orders->map(function($order) {
                return [
                    'id' => $order->id,
                    'sn' => $order->sn,
                    'separate_dec_weight' => $order->separate_dec_weight,
                    'separate_dec_volume' => $order->separate_dec_volume,
                    'separate_dec_page_fee' => $order->separate_dec_page_fee,
                    'separate_dec_method' => $order->separate_dec_method,
                    'separate_dec_other' => $order->separate_dec_other,

                ];
            }),
            'hk_take' => $take_order->orders->map(function($order) {
                return [
                    'id' => $order->id,
                    'sn' => $order->sn,
                    'weight' => $order->hk_take_weight,
                    'hk_take_fee' => $order->hk_take_fee,
                    'hk_take_sign_fee' => $order->hk_take_sign_fee,
                    'hk_take_park_fee' => $order->hk_take_park_fee,
                    'hk_take_remark' => $order->hk_take_remark,
                ];
            }),
            'hk_zs' => $take_order->orders->map(function($order){
                return [
                    'id' => $order->id,
                    'sn' => $order->sn,
                    'hk_zs_weight' => $order->hk_zs_weight,
                    'hk_zs_sign_fee' => $order->hk_zs_sign_fee,
                    'hk_zs_park_fee' => $order->hk_zs_park_fee,
                    'hk_zs_remark' => $order->hk_zs_remark,
                ];
            }),
            'wf' => $take_order->wf->map(function($item) {
                return [
                    'id' => $item->id,
                    'sn' => $item->order->sn,
                    'multi_pack_nums' => $item->multi_pack_nums,
                    'multi_pack_weight' => $item->multi_pack_weight,
                    'multi_pack_price' => $item->multi_pack_price,
                    'carton_hm_nums' => $item->carton_hm_nums,
                    'carton_hm_price' => $item->carton_hm_price,
                    'put_express_nums' => $item->put_express_nums,
                    'put_express_price' => $item->put_express_price,
                    "dbc_nums" => $item->dbc_nums,
                    "dbc_price" => $item->dbc_price,
                    "yx_unload_weight" => $item->yx_unload_weight,
                    "yx_unload_price" => $item->yx_unload_price,
                    "sd_price" => $item->sd_price,
                    "ztc_price" => $item->ztc_price,
                    "ztc_after" => $item->ztc_after,
                ];
            }),
            'special' => $take_order->special->map(function($item) {
                return [
                    "id" => $item->id,
                    "take_order_id" => $item->take_order_id,
                    "price" => $item->price,
                    "weight" => $item->weight,
                    "type" => $item->type,
                    'amount' => $item->amount,
                ];
            })
        ];


        return $this->success([
            'perfect' => $perfect,
        ]);

    }

    public function template_import(Request $request) {
        $id = $request->input('id',  '');
        $tmp_id = $request->input('tmp_id',  '');

        $receivable_take_order = ReceivableGenericModel::find($id);
        if(!$receivable_take_order) {
            return $this->error('提单不存在');
        }

        $tmp_find = ReceivableTmpModel::find($tmp_id);
        if(!$tmp_find){
            return $this->error('模板不存在');
        }

        $tmp_detail = $tmp_find->detail;
        $weight = $receivable_take_order->charging_weight;

        $rate_cny = (new ExchangeRate())->cny_rate();

        DB::beginTransaction();
        try{


        $detail_insert = []; $amount_total = $amount_cny_total = 0;
        foreach ($tmp_detail as $item){

            $rate_error = [];
            if(!isset($rate_cny[$item['currency_id']])){
                $find_currency = CurrencyModel::find($item['currency_id']);
                $find_currency_name = $find_currency->name ?? '';
                $rate_error[] = $find_currency_name . '汇率不存在';
                break;
            }

            $rate = $rate_cny[$item['currency_id']]['rate'];

            $number = $item['number'] == 0 ? $weight : 1;
            $amount = round($item['price'] * $number, 4);
            $amount_cny = round($amount * $rate, 4);

                $amount_total += $amount;
                $amount_cny_total += $amount_cny;

            $detail_insert[] = [
                'take_order_id' => $receivable_take_order->take_order_id,
                'customer_id' => $receivable_take_order->customer_id,
                'flight_id' => $receivable_take_order->flight_id,
                'generic_id' => $id,
                'name' => $item['name'],
                'number' => $number,
                'unit' => $item['unit'],
                'price' => $item['price'],
                'currency_id' => $item['currency_id'],
                'rate' => $rate,
                'amount' => $item['price'] * $number,
                'amount_cny' => $amount_cny,
            ];
        }


        if($rate_error){
            return $this->error('请先添加汇率：' . implode(',', $rate_error));
        }

            ReceivableGenericDetailModel::insert($detail_insert);

            $receivable_take_order->total_amount += $amount_total;
            $receivable_take_order->amount_cny += $amount_cny_total;
            $receivable_take_order->save();

            DB::commit();
        } catch(\Exception $e) {
            DB::rollBack();
            return $this->error($e->getMessage());
        }

        $detail = ReceivableGenericDetailModel::where('generic_id', $id)->get();

        return $this->success(['list' => $detail]);

    }


    public function detail_add(Request $request) {
        $id = $request->input('id');
        $params = $request->all();

        $validator = Validator::make($params, [
            'name' => 'required',
            'amount' => 'required',
            'number' => 'required',
            'currency_id' => 'required',
//            'unit' => 'required',
            'price' => 'required',
//            'rate' => 'required',
//            'amount_cny' => 'required',
        ], [
            'name.required' => '费用名称不能为空',
            'amount.required' => '金额不能为空',
            'number.required' => '数量不能为空',
            'currency_id.required' => '币种不能为空',
            'unit.required' => '单位不能为空',
            'price.required' => '单价不能为空',
            'rate.required' => '汇率不能为空',
            'amount_cny.required' => '金额(CNY)不能为空',
        ]);

        if ($validator->fails()) {
            $err = $validator->errors()->first();
            return $this->error($err);
        }

        $take_order = ReceivableGenericModel::find($id);
        if(!$take_order) {
            return $this->error('提单不存在');
        }

        $detail = new ReceivableGenericDetailModel();
        $detail->take_order_id = $take_order->take_order_id;
        $detail->flight_id = $take_order->flight_id;
        $detail->customer_id = $take_order->customer_id;
        $detail->generic_id = $take_order->id;
        $detail->name = $params['name'];
        $detail->amount = $params['amount'];
        $detail->number = $params['number'] ?? 1;
        $detail->unit = $params['unit'] ?? '';
        $detail->price = $params['price'] ?? 0;
        $detail->currency_id = $params['currency_id'] ?? 0;
        $detail->rate = $params['rate'] ??  0;
        $detail->amount_cny = $params['amount_cny'] ?? 0;
        $detail->save();

        if($params['name'] == '空运单价'){
            $take_order->air_freight_unit_price = $params['amount'];
            $take_order->save();
        }

        if($params['name'] == '总金额'){
            $take_order->total_amount = $params['amount'];
            $take_order->save();
        }

        return $this->success();
    }


    public function detail_update(Request $request, $id) {
        $params = $request->all();

        $detail = ReceivableGenericDetailModel::find($id);
        if(!$detail) {
            return $this->error('明细不存在');
        }

        $validator = Validator::make($params, [
            'name' => 'required',
            'amount' => 'required',
            'number' => 'required',
            'currency_id' => 'required',
//            'unit' => 'required',
            'price' => 'required',
//            'rate' => 'required',
//            'amount_cny' => 'required',
        ], [
            'name.required' => '费用名称不能为空',
            'amount.required' => '金额不能为空',
            'number.required' => '数量不能为空',
            'currency_id.required' => '币种不能为空',
            'unit.required' => '单位不能为空',
            'price.required' => '单价不能为空',
            'rate.required' => '汇率不能为空',
            'amount_cny.required' => '金额(CNY)不能为空',
        ]);

        if ($validator->fails()) {
            $err = $validator->errors()->first();
            return $this->error($err);
        }

        $detail->name = $params['name'];
        $detail->amount = $params['amount'];
        $detail->number = $params['number'] ?? 1;
        $detail->unit = $params['unit'] ?? '';
        $detail->price = $params['price'] ?? 0;
        $detail->currency_id = $params['currency_id'] ?? 0;
        $detail->rate = $params['rate'] ??  0;
        $detail->amount_cny = $params['amount_cny'] ?? 0;
        $detail->save();



        return $this->success();
    }

    public function detail_delete($id) {
        $detail = ReceivableGenericDetailModel::find($id);
        if(!$detail) {
            return $this->error('明细不存在');
        }

        $detail->delete();

        return $this->success();
    }
} 